local_irq_disable();
+ if ( is_hvm_vcpu(prev) )
+ pt_freeze_time(prev);
+
set_current(next);
if ( (per_cpu(curr_vcpu, cpu) == next) || is_idle_vcpu(next) )
obj-y += platform.o
obj-y += pmtimer.o
obj-y += rtc.o
+obj-y += vpt.o
obj-y += vioapic.o
obj-y += vlapic.o
obj-y += vpic.o
return host_tsc + v->arch.hvm_vcpu.cache_tsc_offset;
}
-void hvm_freeze_time(struct vcpu *v)
-{
- struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm;
-
- if ( pt->enabled && pt->first_injected
- && (v->vcpu_id == pt->bind_vcpu)
- && !v->arch.hvm_vcpu.guest_time ) {
- v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
- if ( !test_bit(_VCPUF_blocked, &v->vcpu_flags) )
- {
- stop_timer(&pt->timer);
- rtc_freeze(v);
- }
- }
-}
-
void hvm_migrate_timers(struct vcpu *v)
{
- struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
- struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt;
-
- if ( pt->enabled )
- {
- migrate_timer(&pt->timer, v->processor);
- }
- migrate_timer(&vcpu_vlapic(v)->vlapic_timer, v->processor);
- migrate_timer(&vpmt->timer, v->processor);
+ pit_migrate_timers(v);
rtc_migrate_timers(v);
+ pmtimer_migrate_timers(v);
+ migrate_timer(&vcpu_vlapic(v)->vlapic_timer, v->processor);
}
void hvm_do_resume(struct vcpu *v)
{
ioreq_t *p;
- struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
hvm_stts(v);
- /* Pick up the elapsed PIT ticks and re-enable pit_timer. */
- if ( pt->enabled && (v->vcpu_id == pt->bind_vcpu) && pt->first_injected )
- {
- if ( v->arch.hvm_vcpu.guest_time )
- {
- hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
- v->arch.hvm_vcpu.guest_time = 0;
- }
- pickup_deactive_ticks(pt);
- }
-
- /* Re-enable the RTC timer if needed */
- rtc_thaw(v);
+ pt_thaw_time(v);
/* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */
p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
void hvm_domain_destroy(struct domain *d)
{
- kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer);
+ pit_deinit(d);
rtc_deinit(d);
pmtimer_deinit(d);
int hvm_vcpu_initialise(struct vcpu *v)
{
- struct hvm_domain *platform;
int rc;
if ( (rc = vlapic_init(v)) != 0 )
get_vio(v->domain, v->vcpu_id)->vp_eport =
v->arch.hvm_vcpu.xen_port;
+ INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list);
+
if ( v->vcpu_id != 0 )
return 0;
- /* XXX Below should happen in hvm_domain_initialise(). */
- platform = &v->domain->arch.hvm_domain;
-
- init_timer(&platform->pl_time.periodic_tm.timer,
- pt_timer_fn, v, v->processor);
rtc_init(v, RTC_PORT(0), RTC_IRQ);
pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS);
/*free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);*/
}
-int cpu_get_interrupt(struct vcpu *v, int *type)
-{
- int vector;
-
- if ( (vector = cpu_get_apic_interrupt(v, type)) != -1 )
- return vector;
-
- if ( (v->vcpu_id == 0) &&
- ((vector = cpu_get_pic_interrupt(v, type)) != -1) )
- return vector;
-
- return -1;
-}
-
static void hvm_vcpu_down(void)
{
struct vcpu *v = current;
uint64_t d;
int counter;
- d = muldiv64(hvm_get_clock(s->vcpu) - s->count_load_time, PIT_FREQ, ticks_per_sec(s->vcpu));
+ d = muldiv64(hvm_get_guest_time(s->pt.vcpu) - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu));
switch(s->mode) {
case 0:
case 1:
uint64_t d;
int out;
- d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec(s->vcpu));
+ d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu));
switch(s->mode) {
default:
case 0:
case 5:
if (s->gate < val) {
/* restart counting on rising edge */
- s->count_load_time = hvm_get_clock(s->vcpu);
+ s->count_load_time = hvm_get_guest_time(s->pt.vcpu);
// pit_irq_timer_update(s, s->count_load_time);
}
break;
case 3:
if (s->gate < val) {
/* restart counting on rising edge */
- s->count_load_time = hvm_get_clock(s->vcpu);
+ s->count_load_time = hvm_get_guest_time(s->pt.vcpu);
// pit_irq_timer_update(s, s->count_load_time);
}
/* XXX: disable/enable counting */
void pit_time_fired(struct vcpu *v, void *priv)
{
PITChannelState *s = priv;
- s->count_load_time = hvm_get_clock(v);
+ s->count_load_time = hvm_get_guest_time(v);
}
static inline void pit_load_count(PITChannelState *s, int val)
if (val == 0)
val = 0x10000;
- s->count_load_time = hvm_get_clock(s->vcpu);
+ s->count_load_time = hvm_get_guest_time(s->pt.vcpu);
s->count = val;
period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ);
switch (s->mode) {
case 2:
/* create periodic time */
- s->pt = create_periodic_time (period, 0, 0, pit_time_fired, s);
+ create_periodic_time(&s->pt, period, 0, 0, pit_time_fired, s);
break;
case 1:
/* create one shot time */
- s->pt = create_periodic_time (period, 0, 1, pit_time_fired, s);
+ create_periodic_time(&s->pt, period, 0, 1, pit_time_fired, s);
#ifdef DEBUG_PIT
printk("HVM_PIT: create one shot time.\n");
#endif
break;
default:
+ destroy_periodic_time(&s->pt);
break;
}
}
if (!(val & 0x10) && !s->status_latched) {
/* status latch */
/* XXX: add BCD and null count */
- s->status = (pit_get_out1(s, hvm_get_clock(s->vcpu)) << 7) |
+ s->status = (pit_get_out1(s, hvm_get_guest_time(s->pt.vcpu)) << 7) |
(s->rw_mode << 4) |
(s->mode << 1) |
s->bcd;
for(i = 0;i < 3; i++) {
s = &pit->channels[i];
- if ( s -> pt ) {
- destroy_periodic_time (s->pt);
- s->pt = NULL;
- }
+ destroy_periodic_time(&s->pt);
s->mode = 0xff; /* the init mode */
s->gate = (i != 2);
pit_load_count(s, 0);
PITChannelState *s;
s = &pit->channels[0];
+ s->pt.vcpu = v;
/* the timer 0 is connected to an IRQ */
- s->vcpu = v;
- s++; s->vcpu = v;
- s++; s->vcpu = v;
+ init_timer(&s->pt.timer, pt_timer_fn, &s->pt, v->processor);
+ s++; s->pt.vcpu = v;
+ s++; s->pt.vcpu = v;
register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);
/* register the speaker port */
return;
}
+void pit_migrate_timers(struct vcpu *v)
+{
+ PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit;
+ PITChannelState *s;
+
+ s = &pit->channels[0];
+ if ( s->pt.vcpu == v && s->pt.enabled )
+ migrate_timer(&s->pt.timer, v->processor);
+}
+
+void pit_deinit(struct domain *d)
+{
+ PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
+ PITChannelState *s;
+
+ s = &pit->channels[0];
+ kill_timer(&s->pt.timer);
+}
+
/* the intercept action for PIT DM retval:0--not handled; 1--handled */
static int handle_pit_io(ioreq_t *p)
{
static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
{
PITState *pit = opaque;
- int out = pit_get_out(pit, 2, hvm_get_clock(pit->channels[2].vcpu));
+ int out = pit_get_out(pit, 2,
+ hvm_get_guest_time(pit->channels[2].pt.vcpu));
/* Refresh clock toggles at about 15us. We approximate as 2^14ns. */
unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1;
return ((pit->speaker_data_on << 1) | pit_get_gate(pit, 2) |
return 1;
}
-
-static __inline__ void missed_ticks(struct periodic_time *pt)
-{
- s_time_t missed_ticks;
-
- missed_ticks = NOW() - pt->scheduled;
- if ( missed_ticks > 0 ) {
- missed_ticks = missed_ticks / (s_time_t) pt->period + 1;
- if ( missed_ticks > 1000 ) {
- /* TODO: Adjust guest time togther */
- pt->pending_intr_nr++;
- }
- else {
- pt->pending_intr_nr += missed_ticks;
- }
- pt->scheduled += missed_ticks * pt->period;
- }
-}
-
-/* hook function for the platform periodic time */
-void pt_timer_fn(void *data)
-{
- struct vcpu *v = data;
- struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
-
- pt->pending_intr_nr++;
- pt->scheduled += pt->period;
-
- /* Pick up missed timer ticks. */
- missed_ticks(pt);
-
- /* No need to run the timer while a VCPU is descheduled. */
- if ( test_bit(_VCPUF_running, &v->vcpu_flags) )
- set_timer(&pt->timer, pt->scheduled);
-
- vcpu_kick(v);
-}
-
-/* pick up missed timer ticks at deactive time */
-void pickup_deactive_ticks(struct periodic_time *pt)
-{
- if ( !active_timer(&(pt->timer)) ) {
- missed_ticks(pt);
- set_timer(&pt->timer, pt->scheduled);
- }
-}
-
-/*
- * period: fire frequency in ns.
- */
-struct periodic_time * create_periodic_time(
- u32 period,
- char irq,
- char one_shot,
- time_cb *cb,
- void *data)
-{
- struct periodic_time *pt = &(current->domain->arch.hvm_domain.pl_time.periodic_tm);
- if ( pt->enabled ) {
- stop_timer (&pt->timer);
- pt->enabled = 0;
- }
- pt->bind_vcpu = 0; /* timer interrupt delivered to BSP by default */
- pt->pending_intr_nr = 0;
- pt->first_injected = 0;
- if (period < 900000) { /* < 0.9 ms */
- printk("HVM_PlatformTime: program too small period %u\n",period);
- period = 900000; /* force to 0.9ms */
- }
- pt->period = period;
- pt->irq = irq;
- pt->period_cycles = (u64)period * cpu_khz / 1000000L;
- pt->one_shot = one_shot;
- if ( one_shot ) {
- printk("HVM_PL: No support for one shot platform time yet\n");
- }
- pt->scheduled = NOW() + period;
- set_timer (&pt->timer,pt->scheduled);
- pt->enabled = 1;
- pt->cb = cb;
- pt->priv = data;
- return pt;
-}
-
-void destroy_periodic_time(struct periodic_time *pt)
-{
- if ( pt->enabled ) {
- stop_timer(&pt->timer);
- pt->enabled = 0;
- }
-}
-
/*
* Local variables:
* mode: C
void hvm_interrupt_post(struct vcpu *v, int vector, int type)
{
- struct periodic_time *pt =
- &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
-
- if ( pt->enabled && v->vcpu_id == pt->bind_vcpu
- && is_periodic_irq(v, vector, type) ) {
- if ( !pt->first_injected ) {
- pt->pending_intr_nr = 0;
- pt->last_plt_gtime = hvm_get_guest_time(v);
- pt->scheduled = NOW() + pt->period;
- set_timer(&pt->timer, pt->scheduled);
- pt->first_injected = 1;
- } else {
- pt->pending_intr_nr--;
- pt->last_plt_gtime += pt->period_cycles;
- hvm_set_guest_time(v, pt->last_plt_gtime);
- }
- if (pt->cb)
- pt->cb(v, pt->priv);
- }
+ pt_intr_post(v, vector, type);
switch(type) {
case APIC_DM_EXTINT:
dprintk(XENLOG_G_INFO, "Dom%u callback GSI changed %u -> %u\n",
d->domain_id, old_gsi, gsi);
}
+
+int cpu_has_pending_irq(struct vcpu *v)
+{
+ struct hvm_domain *plat = &v->domain->arch.hvm_domain;
+ int dummy;
+
+ /* APIC */
+ if ( cpu_get_apic_interrupt(v, &dummy) != -1 )
+ return 1;
+
+ /* PIC */
+ if ( !vlapic_accept_pic_intr(v) )
+ return 0;
+
+ return plat->irq.vpic[0].int_output;
+}
+
+int cpu_get_interrupt(struct vcpu *v, int *type)
+{
+ int vector;
+
+ if ( (vector = cpu_get_apic_interrupt(v, type)) != -1 )
+ return vector;
+
+ if ( (v->vcpu_id == 0) &&
+ ((vector = cpu_get_pic_interrupt(v, type)) != -1) )
+ return vector;
+
+ return -1;
+}
+
+int get_intr_vector(struct vcpu* v, int irq, int type)
+{
+ if ( type == APIC_DM_EXTINT )
+ return v->domain->arch.hvm_domain.irq.vpic[irq >> 3].irq_base
+ + (irq & 0x7);
+
+ return domain_vioapic(v->domain)->redirtbl[irq].fields.vector;
+}
+
+int is_irq_masked(struct vcpu *v, int irq)
+{
+ if ( v->domain->arch.hvm_domain.irq.vpic[irq >> 3].imr & (1 << (irq & 7))
+ && domain_vioapic(v->domain)->redirtbl[irq].fields.mask )
+ return 1;
+
+ return 0;
+}
register_portio_handler(v->domain, base, 4, handle_pmt_io);
}
+void pmtimer_migrate_timers(struct vcpu *v)
+{
+ struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt;
+
+ if (vpmt->vcpu == v)
+ migrate_timer(&vpmt->timer, v->processor);
+}
+
void pmtimer_deinit(struct domain *d)
{
PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
/* #define DEBUG_RTC */
-/* Callback that fires the RTC's periodic interrupt */
-void rtc_pie_callback(void *opaque)
+void rtc_periodic_cb(struct vcpu *v, void *opaque)
{
RTCState *s = opaque;
- /* Record that we have fired */
- s->cmos_data[RTC_REG_C] |= (RTC_IRQF|RTC_PF); /* 0xc0 */
- /* Fire */
- hvm_isa_irq_assert(s->vcpu->domain, s->irq);
- /* Remember to fire again */
- s->next_pie = NOW() + s->period;
- set_timer(&s->pie_timer, s->next_pie);
+ s->cmos_data[RTC_REG_C] |= 0xc0;
+}
+
+int is_rtc_periodic_irq(void *opaque)
+{
+ RTCState *s = opaque;
+
+ return !(s->cmos_data[RTC_REG_C] & RTC_AF ||
+ s->cmos_data[RTC_REG_C] & RTC_UF);
}
/* Enable/configure/disable the periodic timer based on the RTC_PIE and
period = 1 << (period_code - 1); /* period in 32 Khz cycles */
period = DIV_ROUND((period * 1000000000ULL), 32768); /* period in ns */
- s->period = period;
#ifdef DEBUG_RTC
printk("HVM_RTC: period = %uns\n", period);
#endif
- s->next_pie = NOW() + s->period;
- set_timer(&s->pie_timer, s->next_pie);
- }
+ create_periodic_time(&s->pt, period, RTC_IRQ, 0, rtc_periodic_cb, s);
+ }
else
- {
- stop_timer(&s->pie_timer);
- }
+ destroy_periodic_time(&s->pt);
}
static void rtc_set_time(RTCState *s);
s->current_tm.tm_hour) )
{
s->cmos_data[RTC_REG_C] |= 0xa0;
- hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
- hvm_isa_irq_assert(s->vcpu->domain, s->irq);
+ hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq);
+ hvm_isa_irq_assert(s->pt.vcpu->domain, s->irq);
}
}
if ( s->cmos_data[RTC_REG_B] & RTC_UIE )
{
s->cmos_data[RTC_REG_C] |= 0x90;
- hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
- hvm_isa_irq_assert(s->vcpu->domain, s->irq);
+ hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq);
+ hvm_isa_irq_assert(s->pt.vcpu->domain, s->irq);
}
/* clear update in progress bit */
break;
case RTC_REG_C:
ret = s->cmos_data[s->cmos_index];
- hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
+ hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq);
s->cmos_data[RTC_REG_C] = 0x00;
break;
default:
return 0;
}
-/* Stop the periodic interrupts from this RTC */
-void rtc_freeze(struct vcpu *v)
-{
- RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
- stop_timer(&s->pie_timer);
-}
-
-/* Start them again */
-void rtc_thaw(struct vcpu *v)
-{
- RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
- if ( (s->cmos_data[RTC_REG_A] & RTC_RATE_SELECT) /* Period is not zero */
- && (s->cmos_data[RTC_REG_B] & RTC_PIE) )
- set_timer(&s->pie_timer, s->next_pie);
-}
-
/* Move the RTC timers on to this vcpu's current cpu */
void rtc_migrate_timers(struct vcpu *v)
{
RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
- migrate_timer(&s->second_timer, v->processor);
- migrate_timer(&s->second_timer2, v->processor);
- migrate_timer(&s->pie_timer, v->processor);
+
+ if ( s->pt.vcpu == v )
+ {
+ if ( s->pt.enabled )
+ migrate_timer(&s->pt.timer, v->processor);
+ migrate_timer(&s->second_timer, v->processor);
+ migrate_timer(&s->second_timer2, v->processor);
+ }
}
void rtc_init(struct vcpu *v, int base, int irq)
{
RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
- s->vcpu = v;
+ s->pt.vcpu = v;
s->irq = irq;
s->cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
s->cmos_data[RTC_REG_B] = RTC_24H;
s->current_tm = gmtime(get_localtime(v->domain));
rtc_copy_date(s);
+ init_timer(&s->pt.timer, pt_timer_fn, &s->pt, v->processor);
init_timer(&s->second_timer, rtc_update_second, s, v->processor);
init_timer(&s->second_timer2, rtc_update_second2, s, v->processor);
- init_timer(&s->pie_timer, rtc_pie_callback, s, v->processor);
s->next_second_time = NOW() + 1000000000ULL;
set_timer(&s->second_timer2, s->next_second_time);
{
RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;
+ kill_timer(&s->pt.timer);
kill_timer(&s->second_timer);
kill_timer(&s->second_timer2);
- kill_timer(&s->pie_timer);
}
{
struct vcpu *v = current;
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
- struct hvm_domain *plat=&v->domain->arch.hvm_domain;
- struct periodic_time *pt = &plat->pl_time.periodic_tm;
+ struct periodic_time *pt;
int intr_type = APIC_DM_EXTINT;
int intr_vector = -1;
int re_injecting = 0;
/* Now let's check for newer interrrupts */
else
{
- if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr )
- {
- hvm_isa_irq_deassert(current->domain, pt->irq);
- hvm_isa_irq_assert(current->domain, pt->irq);
- }
+ pt_update_irq(v);
hvm_set_callback_irq_level();
case APIC_DM_FIXED:
case APIC_DM_LOWEST:
/* Re-injecting a PIT interruptt? */
- if ( re_injecting && pt->enabled &&
- is_periodic_irq(v, intr_vector, intr_type) )
+ if ( re_injecting && (pt = is_pt_irq(v, intr_vector, intr_type)) )
++pt->pending_intr_nr;
/* let's inject this interrupt */
TRACE_3D(TRC_VMX_INTR, v->domain->domain_id, intr_vector, 0);
#include <asm/hvm/svm/intr.h>
#include <asm/x86_emulate.h>
#include <public/sched.h>
+#include <asm/hvm/vpt.h>
#define SVM_EXTRA_DEBUG
static void svm_ctxt_switch_from(struct vcpu *v)
{
- hvm_freeze_time(v);
svm_save_dr(v);
}
switch (ecx)
{
case MSR_IA32_TIME_STAMP_COUNTER:
+ pt_reset(v);
hvm_set_guest_time(v, msr_content);
break;
case MSR_IA32_SYSENTER_CS:
return ret;
}
-s_time_t get_apictime_scheduled(struct vcpu *v)
-{
- struct vlapic *vlapic = vcpu_vlapic(v);
-
- if ( !vlapic_lvt_enabled(vlapic, APIC_LVTT) )
- return -1;
-
- return vlapic->vlapic_timer.expires;
-}
-
int vlapic_find_highest_isr(struct vlapic *vlapic)
{
int result;
return highest_irr;
}
-/* check to see if there is pending interrupt */
-int cpu_has_pending_irq(struct vcpu *v)
-{
- struct hvm_domain *plat = &v->domain->arch.hvm_domain;
- int dummy;
-
- /* APIC */
- if ( cpu_get_apic_interrupt(v, &dummy) != -1 )
- return 1;
-
- /* PIC */
- if ( !vlapic_accept_pic_intr(v) )
- return 0;
-
- return plat->irq.vpic[0].int_output;
-}
-
void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode)
{
struct vlapic *vlapic = vcpu_vlapic(v);
int highest_vector;
unsigned long eflags;
struct vcpu *v = current;
- struct hvm_domain *plat=&v->domain->arch.hvm_domain;
- struct periodic_time *pt = &plat->pl_time.periodic_tm;
unsigned int idtv_info_field;
unsigned long inst_len;
int has_ext_irq;
- if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr )
- {
- hvm_isa_irq_deassert(current->domain, pt->irq);
- hvm_isa_irq_assert(current->domain, pt->irq);
- }
+ pt_update_irq(v);
hvm_set_callback_irq_level();
#include <asm/hvm/vpic.h>
#include <asm/hvm/vlapic.h>
#include <asm/x86_emulate.h>
+#include <asm/hvm/vpt.h>
static void vmx_ctxt_switch_from(struct vcpu *v);
static void vmx_ctxt_switch_to(struct vcpu *v);
static void vmx_ctxt_switch_from(struct vcpu *v)
{
- hvm_freeze_time(v);
-
/* NB. MSR_SHADOW_GS_BASE may be changed by swapgs instrucion in guest,
* so we must save it. */
rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.msr_state.shadow_gs);
switch (ecx) {
case MSR_IA32_TIME_STAMP_COUNTER:
- {
- struct periodic_time *pt =
- &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
- if ( pt->enabled && pt->first_injected
- && v->vcpu_id == pt->bind_vcpu )
- pt->first_injected = 0;
- }
+ pt_reset(v);
hvm_set_guest_time(v, msr_content);
break;
case MSR_IA32_SYSENTER_CS:
*type = APIC_DM_EXTINT;
return vector;
}
-
-int is_periodic_irq(struct vcpu *v, int irq, int type)
-{
- int vec;
- struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
-
- if ( pt->irq != 0 )
- return 0;
-
- if ( type == APIC_DM_EXTINT )
- vec = v->domain->arch.hvm_domain.irq.vpic[0].irq_base;
- else
- vec = domain_vioapic(v->domain)->redirtbl[0].fields.vector;
-
- return (irq == vec);
-}
unsigned int *ecx, unsigned int *edx);
void hvm_stts(struct vcpu *v);
void hvm_set_guest_time(struct vcpu *v, u64 gtime);
-void hvm_freeze_time(struct vcpu *v);
+u64 hvm_get_guest_time(struct vcpu *v);
void hvm_migrate_timers(struct vcpu *v);
void hvm_do_resume(struct vcpu *v);
extern void handle_mmio(unsigned long gpa);
extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
extern void hvm_io_assist(struct vcpu *v);
-extern int cpu_get_interrupt(struct vcpu *v, int *type);
-extern int cpu_has_pending_irq(struct vcpu *v);
#endif /* __ASM_X86_HVM_IO_H__ */
void hvm_set_callback_irq_level(void);
void hvm_set_callback_gsi(struct domain *d, unsigned int gsi);
+int cpu_get_interrupt(struct vcpu *v, int *type);
+int cpu_has_pending_irq(struct vcpu *v);
+int get_intr_vector(struct vcpu* vcpu, int irq, int type);
+int is_irq_masked(struct vcpu *v, int irq);
+
#endif /* __ASM_X86_HVM_IRQ_H__ */
struct vlapic vlapic;
s64 cache_tsc_offset;
u64 guest_time;
+ struct list_head tm_list;
/* For AP startup */
unsigned long init_sipi_sipi_state;
struct vlapic *apic_round_robin(
struct domain *d, uint8_t vector, uint32_t bitmap);
-s_time_t get_apictime_scheduled(struct vcpu *v);
-
int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);
#endif /* __ASM_X86_HVM_VLAPIC_H__ */
#include <xen/errno.h>
#include <xen/time.h>
#include <xen/timer.h>
+#include <xen/list.h>
#include <asm/hvm/vpic.h>
#define PIT_FREQ 1193181
#define PIT_BASE 0x40
+/*
+ * Abstract layer of periodic time, one short time.
+ */
+typedef void time_cb(struct vcpu *v, void *opaque);
+
+struct periodic_time {
+ struct list_head list;
+ char enabled;
+ char one_shot; /* one shot time */
+ int irq;
+ struct vcpu *vcpu; /* vcpu timer interrupt delivers to */
+ u32 pending_intr_nr; /* the couner for pending timer interrupts */
+ u32 period; /* frequency in ns */
+ u64 period_cycles; /* frequency in cpu cycles */
+ s_time_t scheduled; /* scheduled timer interrupt */
+ u64 last_plt_gtime; /* platform time when last IRQ is injected */
+ struct timer timer; /* ac_timer */
+ time_cb *cb;
+ void *priv; /* ponit back to platform time source */
+};
+
typedef struct PITChannelState {
int count; /* can be 65536 */
u16 latched_count;
u8 gate; /* timer start */
s64 count_load_time;
/* irq handling */
- struct vcpu *vcpu;
- struct periodic_time *pt;
+ struct periodic_time pt;
} PITChannelState;
typedef struct PITState {
int64_t next_second_time;
struct timer second_timer;
struct timer second_timer2;
- struct timer pie_timer;
- int period;
- s_time_t next_pie;
- struct vcpu *vcpu;
+ struct periodic_time pt;
} RTCState;
#define FREQUENCE_PMTIMER 3579545
struct vcpu *vcpu;
} PMTState;
-/*
- * Abstract layer of periodic time, one short time.
- */
-typedef void time_cb(struct vcpu *v, void *opaque);
-
-struct periodic_time {
- char enabled; /* enabled */
- char one_shot; /* one shot time */
- char irq;
- char first_injected; /* flag to prevent shadow window */
- u32 bind_vcpu; /* vcpu timer interrupt delivers to */
- u32 pending_intr_nr; /* the couner for pending timer interrupts */
- u32 period; /* frequency in ns */
- u64 period_cycles; /* frequency in cpu cycles */
- s_time_t scheduled; /* scheduled timer interrupt */
- u64 last_plt_gtime; /* platform time when last IRQ is injected */
- struct timer timer; /* ac_timer */
- time_cb *cb;
- void *priv; /* ponit back to platform time source */
-};
-
struct pl_time { /* platform time */
- struct periodic_time periodic_tm;
- struct PITState vpit;
- struct RTCState vrtc;
- struct PMTState vpmt;
+ struct PITState vpit;
+ struct RTCState vrtc;
+ struct PMTState vpmt;
};
-extern u64 hvm_get_guest_time(struct vcpu *v);
-static inline int64_t hvm_get_clock(struct vcpu *v)
-{
- return hvm_get_guest_time(v);
-}
-
#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency)
-/* to hook the ioreq packet to get the PIT initialization info */
-extern void hvm_hooks_assist(struct vcpu *v);
-extern void pickup_deactive_ticks(struct periodic_time *vpit);
-extern struct periodic_time *create_periodic_time(
- u32 period, char irq, char one_shot, time_cb *cb, void *data);
-extern void destroy_periodic_time(struct periodic_time *pt);
+void pt_freeze_time(struct vcpu *v);
+void pt_thaw_time(struct vcpu *v);
+void pt_timer_fn(void *data);
+void pt_update_irq(struct vcpu *v);
+struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type);
+void pt_intr_post(struct vcpu *v, int vector, int type);
+void pt_reset(struct vcpu *v);
+void create_periodic_time(struct periodic_time *pt, u32 period, char irq,
+ char one_shot, time_cb *cb, void *data);
+void destroy_periodic_time(struct periodic_time *pt);
+
int pv_pit_handler(int port, int data, int write);
void pit_init(struct vcpu *v, unsigned long cpu_khz);
+void pit_migrate_timers(struct vcpu *v);
+void pit_deinit(struct domain *d);
void rtc_init(struct vcpu *v, int base, int irq);
-void rtc_deinit(struct domain *d);
-void rtc_freeze(struct vcpu *v);
-void rtc_thaw(struct vcpu *v);
void rtc_migrate_timers(struct vcpu *v);
+void rtc_deinit(struct domain *d);
+int is_rtc_periodic_irq(void *opaque);
void pmtimer_init(struct vcpu *v, int base);
+void pmtimer_migrate_timers(struct vcpu *v);
void pmtimer_deinit(struct domain *d);
-void pt_timer_fn(void *data);
-void pit_time_fired(struct vcpu *v, void *priv);
#endif /* __ASM_X86_HVM_VPT_H__ */